package bootstrap

import (
	"context"
	"log"
	"net/http"
	"os"
	"os/signal"
	"server/app/middleware"
	"server/global"
	"server/routes"
	"syscall"
	"time"

	"github.com/gin-gonic/gin"
)

// 若之后还有其它的分组路由，可以先在 routes 目录下新建一个文件，编写定义路由的方法，然后再到 bootstrap/router.go 调用注册
func setupRouter() *gin.Engine {
	if global.App.Config.App.Env == "production" {
		gin.SetMode(gin.ReleaseMode)
	}
	router := gin.Default()
	router.Use(gin.Logger(), middleware.CustomRecovery())

	//跨域处理
	router.Use(middleware.Cors())

	//前端项目静态资源
	router.Static("/assets", "./static/dist/assets")
	router.StaticFile("/", "./static/dist/index.html")
	router.StaticFile("/favaicon.ico", "./static/dist/favicon.icon")

	//其他静态资源
	router.Static("/public", "./static")
	router.Static("storage", "./storage/app/public")

	//demo路由分组
	apiGroup := router.Group("/api")
	routes.SetApiGroupRoutes(apiGroup)
	//用户路由分组
	userGroup := router.Group("/user")
	routes.SetUserApiRoutes(userGroup)
	//上传路由分组
	uploadGroup := router.Group("/upload")
	routes.SetUploadGroupRoutes(uploadGroup)
	//视频路由分组
	videoGroup := router.Group("/video")
	routes.SetVideoGroupRoutes(videoGroup)

	return router
}

// RunServer 启动服务器
func RunServer() {
	r := setupRouter()

	srv := &http.Server{
		Addr:    ":" + global.App.Config.App.Port,
		Handler: r,
	}

	go func() {
		// ListenAndServeTLS
		if err := srv.ListenAndServe(); /*启动服务器*/ err != nil && err != http.ErrServerClosed {
			log.Fatalf("listen:%s\n", err)
		}
	}()
	//等待中断信号以优雅地关闭服务器(设置五秒的超时时间)
	quit := make(chan os.Signal)                         //创建一个 os.Signal 类型的通道 quit，用来接收中断信号
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) //调用 signal.Notify 函数来监听 SIGINT 和 SIGTERM 信号
	<-quit                                               //阻塞主 goroutine，直到 quit 通道接收到一个信号。
	log.Println("Shutdown Server....服务器终止")
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal("Shutdown Server....终止服务器(err):", err)
	}
	log.Println("Server exiting...服务器正在关闭")

	// r.Run(":" + global.App.Config.App.Port)
}
